package com.hoyin.javaproj;

import java.util.Iterator;

public class GenericsArray<Item> implements Iterable<Item> {
	private int MINIMAL_ACTUAL_SIZE = 4;
	private Item[] a;
	private int actualSize;
	private int size;

	public GenericsArray() {
		a = (Item[]) new Object[0];
	}

	private boolean isFull() {
		return actualSize == size;
	}

	private void resize(Boolean lessenSize) {
		int newActualSize = lessenSize ? (actualSize/MINIMAL_ACTUAL_SIZE - 1)*MINIMAL_ACTUAL_SIZE : (actualSize/MINIMAL_ACTUAL_SIZE + 1)*MINIMAL_ACTUAL_SIZE;
		Item[] t = (Item[]) new Object[newActualSize];
		for (int i = 0; i < this.size; i++) t[i] = this.a[i];
		this.a = t;
		this.actualSize = newActualSize;
	}

	public void append(Item item) {
		if (this.isFull()) this.resize(false);
		this.a[size++] = item;
	}

	public void remove(int index) {
		if (this.isEmpty()) return;
		for (int i = index; i < size; i++) {
			a[i] = a[i + 1];
		}
		this.resize(true);
	}

	public void update(int index, Item item) {
		a[index] = item;
	}

	public Item getItem(int index) {
		return a[index];
	}

	public boolean isEmpty() {
		return size == 0;
	}

	public int getSize() {
		return size;
	}

	public Iterator<Item> iterator() {
		return new ArrayIterator();
	}

	private class ArrayIterator implements Iterator<Item> {
		private int n = size;
		@Override
		public boolean hasNext() {
			return n > 0;
		}

		@Override
		public Item next() {
			return a[--n];
		}
	}

	public static void main() {
		final int TRY_TIMES = 10;
		GenericsArray<Boolean> ga = new GenericsArray<>();
		System.out.println("isEmpty? " + ga.isEmpty());
		System.out.println("Try append(): ");
		for (int i = 0; i < TRY_TIMES; i++) {
			if (i % 2 == 0) ga.append(true);
			else ga.append(false);
			System.out.println("now size: " + ga.getSize());
		}
		System.out.println("isEmpty? " + ga.isEmpty());
		System.out.println("Iterator work start.");
		for (Boolean condition : ga) {
			System.out.println(condition);
		}
		System.out.println("Iterator work done.");
		System.out.println("Try update(): ");
		for (int i = 0; i < TRY_TIMES; i++) {
			if (i % 2 == 0) ga.update(i, false);
		}
		System.out.println("Try getItem(): ");
		for (int i = 0; i < TRY_TIMES; i++) {
			System.out.println(ga.getItem(i));
		}
	}
}
